/*     */ package com.pl.limit.bucket;
/*     */ import com.pl.util.TimeUtil;

import java.util.ArrayList;
/*     */ import java.util.List;
/*     */ import java.util.concurrent.atomic.AtomicReferenceArray;
/*     */ import java.util.concurrent.atomic.LongAdder;
/*     */ import java.util.concurrent.locks.ReentrantLock;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public class ArrayBucket
/*     */ {
/*     */   protected int windowLengthInMs;
/*     */   protected int sampleCount;
/*     */   protected int intervalInMs;
/*     */   private double intervalInSecond;
/*     */   protected final AtomicReferenceArray<Window> array;
/*  45 */   private final ReentrantLock updateLock = new ReentrantLock();
/*     */   
/*     */   public ArrayBucket(int sampleCount, int intervalInMs) {
/*  48 */     if (sampleCount <= 0 || intervalInMs <= 0 || intervalInMs % sampleCount != 0)
/*     */     {
/*     */       
/*  51 */       throw new IllegalArgumentException("Parameter invalid!");
/*     */     }
/*  53 */     this.windowLengthInMs = intervalInMs / sampleCount;
/*  54 */     this.intervalInMs = intervalInMs;
/*  55 */     this.intervalInSecond = intervalInMs / 1000.0D;
/*  56 */     this.sampleCount = sampleCount;
/*  57 */     this.array = new AtomicReferenceArray<>(sampleCount);
/*     */   }
/*     */ 
/*     */ 
/*     */ 
/*     */   
/*     */   public Window currentWindow() {
/*  64 */     return currentWindow(TimeUtil.currentTimeMillis());
/*     */   }
/*     */ 
/*     */ 
/*     */ 
/*     */   
/*     */   public LongAdder newEmptyBucket(long timeMillis) {
/*  71 */     return new LongAdder();
/*     */   }
/*     */ 
/*     */ 
/*     */ 
/*     */   
/*     */   protected Window resetWindowTo(Window window, long startTime) {
/*  78 */     window.resetTo(startTime);
/*  79 */     window.value().reset();
/*  80 */     return window;
/*     */   }
/*     */   
/*     */   private int calculateTimeIdx(long timeMillis) {
/*  84 */     long timeId = timeMillis / this.windowLengthInMs;
/*  85 */     return (int)(timeId % this.array.length());
/*     */   }
/*     */   
/*     */   protected long calculateWindowStart(long timeMillis) {
/*  89 */     return timeMillis - timeMillis % this.windowLengthInMs;
/*     */   }
/*     */ 
/*     */ 
/*     */ 
/*     */   
/*     */   public Window currentWindow(long timeMillis) {
/*  96 */     if (timeMillis < 0L) {
/*  97 */       return null;
/*     */     }
/*  99 */     int idx = calculateTimeIdx(timeMillis);
/*     */     
/* 101 */     long windowStart = calculateWindowStart(timeMillis);
/*     */ 
/*     */     
/*     */     while (true) {
/* 105 */       Window old = this.array.get(idx);
/* 106 */       if (old == null) {
/*     */         
/* 108 */         Window window = new Window(this.windowLengthInMs, windowStart, newEmptyBucket(timeMillis));
/* 109 */         if (this.array.compareAndSet(idx, null, window))
/*     */         {
/* 111 */           return window;
/*     */         }
/*     */         
/* 114 */         Thread.yield(); continue;
/*     */       } 
/* 116 */       if (windowStart == old.windowStart())
/*     */       {
/* 118 */         return old; } 
/* 119 */       if (windowStart > old.windowStart()) {
/*     */         
/* 121 */         if (this.updateLock.tryLock()) {
/*     */           
/*     */           try {
/* 124 */             return resetWindowTo(old, windowStart);
/*     */           } finally {
/* 126 */             this.updateLock.unlock();
/*     */           } 
/*     */         }
/*     */         
/* 130 */         Thread.yield(); continue;
/*     */       } 
/* 132 */       if (windowStart < old.windowStart())
/*     */         break; 
/* 134 */     }  return new Window(this.windowLengthInMs, windowStart, newEmptyBucket(timeMillis));
/*     */   }
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   
/*     */   public Window getPreviousWindow(long timeMillis) {
/* 143 */     if (timeMillis < 0L) {
/* 144 */       return null;
/*     */     }
/* 146 */     int idx = calculateTimeIdx(timeMillis - this.windowLengthInMs);
/* 147 */     timeMillis -= this.windowLengthInMs;
/* 148 */     Window wrap = this.array.get(idx);
/*     */     
/* 150 */     if (wrap == null || isWindowDeprecated(wrap)) {
/* 151 */       return null;
/*     */     }
/*     */     
/* 154 */     if (wrap.windowStart() + this.windowLengthInMs < timeMillis) {
/* 155 */       return null;
/*     */     }
/*     */     
/* 158 */     return wrap;
/*     */   }
/*     */ 
/*     */ 
/*     */ 
/*     */   
/*     */   public Window getPreviousWindow() {
/* 165 */     return getPreviousWindow(TimeUtil.currentTimeMillis());
/*     */   }
/*     */ 
/*     */ 
/*     */ 
/*     */   
/*     */   public LongAdder getWindowValue(long timeMillis) {
/* 172 */     if (timeMillis < 0L) {
/* 173 */       return null;
/*     */     }
/* 175 */     int idx = calculateTimeIdx(timeMillis);
/*     */     
/* 177 */     Window bucket = this.array.get(idx);
/*     */     
/* 179 */     if (bucket == null || !bucket.isTimeInWindow(timeMillis)) {
/* 180 */       return null;
/*     */     }
/*     */     
/* 183 */     return bucket.value();
/*     */   }
/*     */ 
/*     */ 
/*     */ 
/*     */   
/*     */   public boolean isWindowDeprecated(Window window) {
/* 190 */     return isWindowDeprecated(TimeUtil.currentTimeMillis(), window);
/*     */   }
/*     */   
/*     */   public boolean isWindowDeprecated(long time, Window window) {
/* 194 */     return (time - window.windowStart() > this.intervalInMs);
/*     */   }
/*     */   
/*     */   public List<Window> list() {
/* 198 */     return list(TimeUtil.currentTimeMillis());
/*     */   }
/*     */   
/*     */   public List<Window> list(long validTime) {
/* 202 */     int size = this.array.length();
/* 203 */     List<Window> result = new ArrayList<>(size);
/*     */     
/* 205 */     for (int i = 0; i < size; i++) {
/* 206 */       Window windowWrap = this.array.get(i);
/* 207 */       if (windowWrap != null && !isWindowDeprecated(validTime, windowWrap))
/*     */       {
/*     */         
/* 210 */         result.add(windowWrap);
/*     */       }
/*     */     } 
/* 213 */     return result;
/*     */   }
/*     */ 
/*     */ 
/*     */ 
/*     */   
/*     */   public List<Window> listAll() {
/* 220 */     int size = this.array.length();
/* 221 */     List<Window> result = new ArrayList<>(size);
/*     */     
/* 223 */     for (int i = 0; i < size; i++) {
/* 224 */       Window windowWrap = this.array.get(i);
/* 225 */       if (windowWrap != null)
/*     */       {
/*     */         
/* 228 */         result.add(windowWrap);
/*     */       }
/*     */     } 
/* 231 */     return result;
/*     */   }
/*     */ 
/*     */ 
/*     */ 
/*     */   
/*     */   public List<LongAdder> values() {
/* 238 */     return values(TimeUtil.currentTimeMillis());
/*     */   }
/*     */   
/*     */   public List<LongAdder> values(long timeMillis) {
/* 242 */     if (timeMillis < 0L) {
/* 243 */       return new ArrayList<>();
/*     */     }
/* 245 */     int size = this.array.length();
/* 246 */     List<LongAdder> result = new ArrayList<>(size);
/*     */     
/* 248 */     for (int i = 0; i < size; i++) {
/* 249 */       Window window = this.array.get(i);
/* 250 */       if (window != null && !isWindowDeprecated(timeMillis, window))
/*     */       {
/*     */         
/* 253 */         result.add(window.value()); } 
/*     */     } 
/* 255 */     return result;
/*     */   }
/*     */ }


/* Location:              E:\code\common\cmsr-common-ops-log\1.0.0-SNAPSHOT\cmsr-common-ops-log-1.0.0-SNAPSHOT.jar!\com\cmsr\common\ops\log\limit\bucket\ArrayBucket.class
 * Java compiler version: 8 (52.0)
 * JD-Core Version:       1.1.3
 */